/////////////////////////////////////////////////////////////////////
//
//  MOE Framework (Meta Object Encapsulation Framework)
//
//  Original Author: Wiksy Wang, 2011
//
/////////////////////////////////////////////////////////////////////

#include "ObjectTypeManager.h"

#include <xstring>
#include "ClassMeta.h"

namespace MOE
{

ObjectTypeManager::ObjectTypeManager()
	: _idToMeta()
	, _nameToMeta()
{
	RegisterAtomClasses();
}

void ObjectTypeManager::RegisterAtomClasses()
{
	RegisterClassInternal(ClassMetaHolder<int>::Instance(), ClassMetaHolder<int>::ID(), "int", sizeof(int), AT_Integer);
	RegisterClassInternal(ClassMetaHolder<float>::Instance(), ClassMetaHolder<float>::ID(), "float", sizeof(float), AT_Float);
	RegisterClassInternal(ClassMetaHolder<bool>::Instance(), ClassMetaHolder<bool>::ID(), "bool", sizeof(bool), AT_Bool);
	RegisterClassInternal(ClassMetaHolder<std::string>::Instance(), ClassMetaHolder<std::string>::ID(), "string", sizeof(std::wstring), AT_String);
	RegisterClassInternal(ClassMetaHolder<std::wstring>::Instance(), ClassMetaHolder<std::wstring>::ID(), "wstring", sizeof(std::wstring), AT_WideString);
}

ClassMetaProxy ObjectTypeManager::RegisterClassInternal(ClassMetaHolderBase* holder, ClassIDType id, const RawByteVector& className, size_t classSize, AtomTypes atomType)
{
	if (_idToMeta.find(id) == _idToMeta.end())
	{
		_idToMeta[id] = holder;
	}
	else
	{
		return ClassMetaProxy(NULL);
	}

	if (_nameToMeta.find(className) == _nameToMeta.end())
	{
		_nameToMeta[className] = holder;
	}
	else
	{
		return ClassMetaProxy(NULL);
	}

	holder->_meta = new ClassMeta(id, className, classSize, atomType);
	return ClassMetaProxy(holder->_meta);
}

ClassIDType ObjectTypeManager::GetClassID(const RawByteVector& className) const
{
	NameToMetaMap::const_iterator it = _nameToMeta.find(className);
	if (it == _nameToMeta.end())
	{
		return 0;
	}
	else
	{
		return it->second->GetID();
	}
}

ClassMetaProxy ObjectTypeManager::GetClassMeta(const ClassIDType classID) const
{
	IDToMetaMap::const_iterator it = _idToMeta.find(classID);
	if (it == _idToMeta.end())
	{
		return ClassMetaProxy(NULL);
	}
	else
	{
		return ClassMetaProxy(it->second->_meta);
	}
}

ClassMetaProxy ObjectTypeManager::GetClassMeta(const RawByteVector& className) const
{
	NameToMetaMap::const_iterator it = _nameToMeta.find(className);
	if (it == _nameToMeta.end())
	{
		return ClassMetaProxy(NULL);
	}
	else
	{
		return ClassMetaProxy(it->second->_meta);
	}
}

}
